﻿using JNPF.Basics.Logic;
using JNPF.Basics.Logic.WorkFlow.FlowFlowDynamic;
using JNPF.Basics.Models;
using JNPF.Basics.Models.WorkFlow.Dtos.FlowBefore;
using JNPF.Basics.Models.WorkFlow.Model;
using JNPF.Utils;
using JNPF.Utils.Controller;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Threading.Tasks;

namespace JNPF.Basics.Controller
{
    /// <summary>
    /// 待我审批
    /// 版 本：V3.0.0
    /// 版 权：引迈信息技术有限公司（https://www.jnpfsoft.com）
    /// 作 者：JNPF开发平台组
    /// 日 期：2018-06-11
    /// </summary>
    [Route("api/WorkFlow/[controller]")]
    public class FlowBeforeController : BaseApiController
    {
        private FlowTaskBll flowTaskBll = new FlowTaskBll();
        private FlowTaskNodeBll flowTaskNodeBll = new FlowTaskNodeBll();
        private FlowTaskOperatorBll flowTaskOperatorBll = new FlowTaskOperatorBll();
        private FlowTaskOperatorRecordBll flowTaskOperatorRecordBll = new FlowTaskOperatorRecordBll();
        private FlowEngineBll flowEngineBll = new FlowEngineBll();
        private UserBll userBll = new UserBll();
        private OrganizeBll organizeBll = new OrganizeBll();
        private FlowFlowDynamicBll flowFlowDynamicBll = new FlowFlowDynamicBll();

        #region GET
        /// <summary>
        /// 列表
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <param name="category">分类</param>
        /// <returns></returns>
        [HttpGet("List/{category}")]
        public async Task<ResponseResult> GetList([FromQuery] FlowBeforeListQuery input, string category)
        {
            try
            {
                var pageInput = input.MapTo<PageInput>();
                pageInput.queryJson = new { input.startTime, input.endTime, input.flowCategory, input.flowId, input.creatorUserId }.ToJson();
                var output = new PageResult<FlowBeforeListOutput>();
                var outlist = new List<FlowBeforeListOutput>();
                var page = new PageOutput();
                var flowEngineEntityList = await flowEngineBll.GetList();
                switch (category)
                {
                    case "1":
                        var data = await flowTaskBll.GetWaitList(pageInput);
                        outlist = data.list.MapToList<FlowBeforeListOutput>();
                        foreach (var item in outlist)
                        {
                            item.formData = flowEngineEntityList.Find(x => x.Id.Equals(item.flowId)).FormTemplateJson;
                            item.formType = flowEngineEntityList.Find(x => x.Id.Equals(item.flowId)).FormType;
                            item.userName = userBll.GetUserName(item.creatorUserId);
                            item.delegateId = item.id;
                        }
                        page = data.pagination;
                        break;
                    case "2":
                        data = await flowTaskBll.GetTrialList(pageInput);
                        outlist = data.list.MapToList<FlowBeforeListOutput>();
                        foreach (var item in outlist)
                        {
                            item.formData = flowEngineEntityList.Find(x => x.Id.Equals(item.flowId)).FormTemplateJson;
                            item.formType = flowEngineEntityList.Find(x => x.Id.Equals(item.flowId)).FormType;
                            item.userName = userBll.GetUserName(item.creatorUserId);
                            item.delegateId = "0";
                        }
                        page = data.pagination;
                        break;
                    case "3":
                        data = await flowTaskBll.GetCirculateList(pageInput);
                        outlist = data.list.MapToList<FlowBeforeListOutput>();
                        foreach (var item in outlist)
                        {
                            item.formData = flowEngineEntityList.Find(x => x.Id.Equals(item.flowId)).FormTemplateJson;
                            item.formType = flowEngineEntityList.Find(x => x.Id.Equals(item.flowId)).FormType;
                            item.userName = userBll.GetUserName(item.creatorUserId);
                            item.delegateId = "0";
                        }
                        page = data.pagination;
                        break;
                    default:
                        break;
                }
                output.list = outlist;
                output.pagination = page;
                return Success(output);
            }
            catch (Exception e)
            {
                LogFactory.GetLogger().Error(e);
                return Error("未知错误");
            }
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<ResponseResult> GetInfo(string id)
        {
            var output = new FlowBeforeInfoOutput();
            var userList = await userBll.GetList();
            var flowTaskEntity = await flowTaskBll.GetInfo(id);
            var flowTaskNodeList = (await flowTaskNodeBll.GetList(flowTaskEntity.Id)).FindAll(x => "0".Equals(x.State));
            output.freeApprover = (int)flowEngineBll.GetFlowNodeList(flowTaskEntity.ThisStepId, flowTaskNodeList);
            output.flowTaskInfo = flowTaskEntity.MapTo<FlowTaskModel>();
            output.flowTaskOperatorList = (await flowTaskOperatorBll.GetList(flowTaskEntity.Id)).FindAll(t => "0".Equals(t.State)).MapToList<FlowTaskOperatorModel>();
            var flowTaskOperatorRecordList = (await flowTaskOperatorRecordBll.GetList(flowTaskEntity.Id)).MapToList<FlowTaskOperatorRecordModel>();
            var flowTaskNodes = flowTaskNodeList.MapToList<FlowTaskNodeModel>();
            var thisNodeFlag = true;
            foreach (var modelList in flowTaskNodes)
            {
                var userAllModels = new List<string>();
                var models = modelList.nodePropertyJson.ToObject<ChildNodeModelList>();
                #region 流程图节点颜色类型
                if (thisNodeFlag)
                {
                    modelList.type = "0";
                }
                if (flowTaskEntity.ThisStepId==modelList.nodeCode)
                {
                    modelList.type = "1";
                    thisNodeFlag = false;
                }
                #endregion

                if (modelList.nodeType == "start")
                {
                    userAllModels.Add(userBll.GetUserName(flowTaskEntity.CreatorUserId));
                }
                else
                {
                    var userModel = userList.Find(x => x.Id == flowTaskEntity.CreatorUserId);
                    if (models.assigneeType == (int)FlowTaskOperatorEnum.LaunchCharge)
                    {
                        //发起者【发起主管】
                        foreach (var manageId in userModel.ManagerId.Split(','))
                        {
                            var manager = userList.Find(x => x.Id == manageId);
                            if (manager != null)
                            {
                                userAllModels.Add(userBll.GetUserName(manager.Id));
                            }
                        }
                        modelList.assigneeName = GetAssigneeName(FlowTaskOperatorEnum.LaunchCharge, 1);
                    }
                    else if (models.assigneeType == (int)FlowTaskOperatorEnum.DepartmentCharge)
                    {
                        //发起者【部门主管】
                        var organize = (await organizeBll.GetList()).Find(x => x.Id == userModel.OrganizeId);
                        if (organize != null)
                        {
                            userAllModels.Add(userBll.GetUserName(organize.ManagerId));
                        }
                        modelList.assigneeName = GetAssigneeName(FlowTaskOperatorEnum.DepartmentCharge, 2);
                    }
                    else if (models.assigneeType == (int)FlowTaskOperatorEnum.InitiatorMe)
                    {
                        //发起者【发起本人】
                        userAllModels.Add(userBll.GetUserName(userModel.Id));
                        modelList.assigneeName = GetAssigneeName(FlowTaskOperatorEnum.InitiatorMe, 3);
                    }
                    else if (models.assigneeType == (int)FlowTaskOperatorEnum.FreeApprover)
                    {
                        //发起者【授权审批人】
                        var freeAppList = output.flowTaskOperatorList.FindAll(t => t.nodeCode == models.nodeId);
                        if (freeAppList.Count > 0)
                        {
                            var flowTask = freeAppList[0];
                            userAllModels.Add(userBll.GetUserName(flowTask.handleId));
                        }
                        else
                        {
                            userAllModels.Add("");
                        }
                        modelList.assigneeName = GetAssigneeName(FlowTaskOperatorEnum.FreeApprover, 7);
                    }
                    else
                    {
                        foreach (var approverPos in models.approverPos)
                        {
                            var approverPosUser = userList.FindAll(x => x.PositionId.Contains(approverPos));
                            foreach (var item in approverPosUser)
                            {
                                userAllModels.Add(userBll.GetUserName(item.Id));
                            }
                        }
                    }
                    foreach (var approvers in models.approvers)
                    {
                        var approversUser = userList.Find(x => x.Id == approvers);
                        if (approversUser.Account != null)
                        {
                            var userName = approversUser.RealName + "/" + approversUser.Account;
                            if (!userAllModels.Contains(userName))
                            {
                                userAllModels.Add(userName);
                            }

                        }
                    }
                    if (!models.assigneeType.IsNullOrEmpty())
                    {
                        var ftoEunm = (FlowTaskOperatorEnum)Enum.Parse(typeof(FlowTaskOperatorEnum), models.assigneeType.ToString());
                        modelList.assigneeName = GetAssigneeName(ftoEunm, Convert.ToInt32(models.assigneeType));
                    }
                }
                modelList.userName = string.Join(",", userAllModels);
            }
            output.flowTaskNodeList = flowTaskNodes;
            if (flowTaskOperatorRecordList.Count > 0)
            {
                foreach (var item in flowTaskOperatorRecordList)
                {
                    var user = userList.Find(x => x.Id == item.handleId);
                    item.userName = user.RealName + "/" + user.Account;
                }
            }
            output.flowTaskOperatorRecordList = flowTaskOperatorRecordList;
            output.flowFormInfo = (await flowEngineBll.GetInfo(flowTaskEntity.FlowId)).FormTemplateJson;
            var nodeJson = output.flowTaskNodeList.Find(x => x.nodeCode == output.flowTaskInfo.thisStepId);
            if (!nodeJson.IsEmpty() && !nodeJson.nodePropertyJson.IsEmpty())
            {
                var childNodeModelList = nodeJson.nodePropertyJson.ToObject<ChildNodeModelList>();
                if (childNodeModelList.IsNotEmptyOrNull() && childNodeModelList.formOperates.IsNotEmptyOrNull())
                {
                    output.formOperates = childNodeModelList.formOperates;
                }
            }
            return Success(output);
        }
        #endregion

        #region POST
        /// <summary>
        /// 审核同意
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="flowHandleModel">流程经办</param>
        /// <returns></returns>
        [HttpPost("Audit/{id}")]
        public async Task<ResponseResult> Audit(string id, [FromBody] FlowHandleModel flowHandleModel)
        {
            
            var flowTaskOperatorEntity = await flowTaskOperatorBll.GetInfo(id);
            var flowTaskEntity = await flowTaskBll.GetInfo(flowTaskOperatorEntity.TaskId);
            var flowEngine = await flowEngineBll.GetInfo(flowTaskEntity.FlowId);
            if (flowEngine.FormType == 2)
            {
                var data = (flowHandleModel.formData.ToJson().ToObject())["data"].ToString();
                await flowFlowDynamicBll.Save(flowTaskEntity.Id, flowTaskEntity.FlowId, data, 1);
            }
            else
            {
                var className = StringHelper.FunctionStr(flowHandleModel.enCode);
                Assembly asm=null;
                //遍历获取所有程序及
                var refAssembyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
                foreach (var item in refAssembyNames)
                {
                    if (item.Name.Equals("JNPF.Basics.Logic"))
                    {
                        asm = Assembly.Load(item);
                    }
                }
                dynamic obj = asm.CreateInstance("JNPF.Basics.Logic." + className+ "Bll", true);
                if (obj!=null)
                {
                    var dic = flowHandleModel.formData.ToObject<Dictionary<string, object>>();
                    CommonHelper.SysTableDateCon(dic);
                    obj.Save(flowTaskEntity.Id, dic);
                }
            }
            if (flowHandleModel.delegateId.IsNotEmptyOrNull() && !"0".Equals(flowHandleModel.delegateId))
            {
                flowTaskOperatorEntity = await flowTaskOperatorBll.GetInfo(flowHandleModel.delegateId);
            }
            if (flowTaskOperatorEntity == null)
            {
                return Error("审核失败");
            }
            else
            {
                flowTaskEntity = await flowTaskBll.GetInfo(flowTaskOperatorEntity.TaskId);
                await flowTaskBll.Audit(flowTaskEntity, flowTaskOperatorEntity, flowHandleModel, flowHandleModel.freeApproverUserId);
                //await this.HandleEvent(FlowHandleEventEnum.Audit, flowTaskEntity);
                return Success("审核成功");
            }
        }

        /// <summary>
        /// 审核拒绝
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="flowHandleModel">流程经办</param>
        /// <returns></returns>
        [HttpPost("Reject/{id}")]
        public async Task<ResponseResult> Reject(string id, [FromBody] FlowHandleModel flowHandleModel)
        {
            var flowTaskOperatorEntity = await flowTaskOperatorBll.GetInfo(id);
            var flowTaskEntity = await flowTaskBll.GetInfo(flowTaskOperatorEntity.TaskId);
            var flowEngine = await flowEngineBll.GetInfo(flowTaskEntity.FlowId);
            if (flowEngine.FormType==2)
            {
                var data = (flowHandleModel.formData.ToJson().ToObject())["data"].ToString();
                await flowFlowDynamicBll.Save(flowTaskEntity.Id, flowTaskEntity.FlowId, data, 1);
            }
            else
            {
                var className = StringHelper.FunctionStr(flowHandleModel.enCode);
                Assembly asm = null;
                //遍历获取所有程序及
                var refAssembyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
                foreach (var item in refAssembyNames)
                {
                    if (item.Name.Equals("JNPF.Basics.Logic"))
                    {
                        asm = Assembly.Load(item);
                    }
                }
                dynamic obj = asm.CreateInstance("JNPF.Basics.Logic." + className + "Bll", true);
                if (obj != null)
                {
                    var dic = flowHandleModel.formData.ToObject<Dictionary<string, object>>();
                    CommonHelper.SysTableDateCon(dic);
                    obj.Save(flowTaskEntity.Id, dic);
                }
            }
            if (flowHandleModel.delegateId.IsNotEmptyOrNull() && !"0".Equals(flowHandleModel.delegateId))
            {
                flowTaskOperatorEntity = await flowTaskOperatorBll.GetInfo(flowHandleModel.delegateId);
            }
            if (flowTaskOperatorEntity == null)
            {
                return Error("驳回失败");
            }
            else
            {
                flowTaskEntity = await flowTaskBll.GetInfo(flowTaskOperatorEntity.TaskId);
                await flowTaskBll.Reject(flowTaskEntity, flowTaskOperatorEntity, flowHandleModel);
                //await this.HandleEvent(FlowHandleEventEnum.Reject, flowTaskEntity);
                return Success("驳回成功");
            }
        }
        /// <summary>
        /// 撤回审核
        /// 注意：在撤销流程时要保证你的下一节点没有处理这条记录；如已处理则无法撤销流程。
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="flowHandleModel">流程经办</param>
        /// <returns></returns>
        [HttpPost("Recall/{id}")]
        public async Task<ResponseResult> Recall(string id, [FromBody] FlowHandleModel flowHandleModel)
        {
            var flowTaskOperatorRecordEntity = await flowTaskOperatorRecordBll.GetInfo(id);
            flowTaskOperatorRecordEntity.HandleOpinion = flowHandleModel.handleOpinion;
            var flowTaskEntity = await flowTaskBll.GetInfo(flowTaskOperatorRecordEntity.TaskId);
            var flowTaskNodeEntityList = await flowTaskNodeBll.GetList(flowTaskOperatorRecordEntity.TaskId);
            var flowTaskNodeEntity = flowTaskNodeEntityList.Find(t => t.Id == flowTaskOperatorRecordEntity.TaskNodeId);
            var nextFlowTaskNodeEntity = flowTaskNodeEntityList.Find(t => t.SortCode == flowTaskNodeEntity.SortCode + 1);
            //当前节点属性
            FlowNodeModel nodeModel = flowTaskNodeEntity.NodePropertyJson.ToObject<FlowNodeModel>();
            if (nodeModel.HandlerInitiator == FlowTaskOperatorEnum.FreeApprover)
            {
                var flowTaskOperatorList = (await flowTaskOperatorBll.GetList(flowTaskEntity.Id)).FindAll(t => t.TaskNodeId == flowTaskOperatorRecordEntity.TaskNodeId);
                var thisFlowTaskOperator = flowTaskOperatorList.Find(t => t.Id == flowTaskOperatorRecordEntity.TaskOperatorId);
                var nextFlowTaskOperator = flowTaskOperatorList.Find(t => t.CreatorTime > thisFlowTaskOperator.CreatorTime);
                if (nextFlowTaskOperator.Completion > 0)
                {
                    return Error("当前流程被处理，无法撤回流程");
                }
                nextFlowTaskNodeEntity = flowTaskNodeEntity;
            }
            if (flowTaskEntity.Status == 2 || flowTaskEntity.Status == 3 || nextFlowTaskNodeEntity.Completion > 0)
            {
                return Error("当前流程被处理，无法撤回流程");
            }
            else
            {
                await flowTaskBll.Recall(flowTaskEntity, flowTaskNodeEntity, flowTaskOperatorRecordEntity, nextFlowTaskNodeEntity.Id);
                //await this.HandleEvent(FlowHandleEventEnum.Recall, flowTaskEntity);
                return Success("撤回成功");
            }
        }

        /// <summary>
        /// 终止审核
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="flowHandleModel">流程经办</param>
        /// <returns></returns>
        [HttpPost("Cancel/{id}")]
        public async Task<ResponseResult> Cancel(string id, [FromBody] FlowHandleModel flowHandleModel)
        {
            var flowTaskEntity = await flowTaskBll.GetInfo(id);
            await flowTaskBll.Cancel(flowTaskEntity, flowHandleModel);
            //await this.HandleEvent(FlowHandleEventEnum.Cancel, flowTaskEntity);
            return Success("终止成功");
        }

        /// <summary>
        /// 转办
        /// </summary>
        /// <param name="id">流程经办主键id</param>
        /// <param name="flowHandleModel"></param>
        /// <returns></returns>
        [HttpPost("Transfer/{id}")]
        public async Task<ResponseResult> Transfer(string id, [FromBody] FlowHandleModel flowHandleModel)
        {
            var flowOperatorEntity = await flowTaskOperatorBll.GetInfo(id);
            if (flowOperatorEntity.IsNullOrEmpty())
            {
                return Error("数据不存在");
            }
            flowOperatorEntity.HandleId = flowHandleModel.freeApproverUserId;
            var isOk = await flowTaskOperatorBll.Update(flowOperatorEntity);
            return isOk > 0 ? Success("转办成功") : Error("转办失败");
        }
        #endregion

        #region Method
        /// <summary>
        /// 经办事件
        /// </summary>
        /// <param name="flowHandleEvent">操作</param>
        /// <param name="flowTaskEntity">流程任务</param>
        private async Task HandleEvent(FlowHandleEventEnum flowHandleEvent, FlowTaskEntity flowTaskEntity)
        {
            if (flowTaskEntity.FlowCode == FlowModuleEnum.CRM_Order)
            {
                await new OrderBll().FlowHandleEvent(flowHandleEvent, flowTaskEntity);
            }
        }

        /// <summary>
        /// 获取代理人名称
        /// </summary>
        /// <param name="flowTaskOperatorEnum"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        private string GetAssigneeName(FlowTaskOperatorEnum flowTaskOperatorEnum, int index)
        {
            Type enumType = flowTaskOperatorEnum.GetType();
            FieldInfo fieldInfo = enumType.GetField(Enum.GetName(typeof(FlowTaskOperatorEnum), index));
            DescriptionAttribute attr = Attribute.GetCustomAttribute(fieldInfo, typeof(DescriptionAttribute), false) as DescriptionAttribute;
            return attr.Description;
        }
        #endregion
    }
}
